#include "engine/task.h"
#include "engine/result_codes.h"
#include "engine/game_state.h"
#include "engine/timer_task.h"

#include "cppunit/TestFixture.h"
#include "cppunit/extensions/HelperMacros.h"


using namespace engine;

class TimerTaskTest : public CppUnit::TestFixture {    
    CPPUNIT_TEST_SUITE(TimerTaskTest);
    CPPUNIT_TEST(testTimer);    
    CPPUNIT_TEST(testCountDown);
    CPPUNIT_TEST_SUITE_END();

public:  

    void testTimer() { 
        TimerTask timer_task(game_state_);
        int result;
        int64 sleep_time = 0;
        result = timer_task.Start();
        
        //check Start() result code
        CPPUNIT_ASSERT(result >= 0);
 
        //sleep for 50 millisecs
        sleep_time += 40000;
        Sleep(50);
        
        result = timer_task.Update();
        
        //check Update() result code
        CPPUNIT_ASSERT(result >= 0);

        //sleep for 50 millisecs
        sleep_time += 40000;
        Sleep(50);

        result = timer_task.Update();
        
        //check Update() result code
        CPPUNIT_ASSERT(result >= 0);

        //make sure that the timer properly recorded the passage of time
        //note that Sleep is not terribly accurate... it sleeps about 1 millisec
        //so build some wiggle room into the test
        CPPUNIT_ASSERT(timer_task.GetElapsedMicroseconds() >= 40000);

        CPPUNIT_ASSERT(timer_task.GetTotalMicroseconds() >= sleep_time);
        
        int64 pause_time = timer_task.GetTotalMicroseconds();

        timer_task.OnSuspend();        

        Sleep(1000);

        result = timer_task.OnResume();
        //check OnResume() result code
        CPPUNIT_ASSERT(result >= 0);

        //check time did not pass while paused
        CPPUNIT_ASSERT(pause_time == timer_task.GetTotalMicroseconds());       
    }

    void testCountDown() {        
        int result;

        int64 microseconds = 500000; //.5 seconds
        CountDownTask count_down(game_state_, microseconds);
      
        result = count_down.Start();

        while(!count_down.GetCanKill()) {
            Sleep(50);
            result = count_down.Update();
            CPPUNIT_ASSERT(result >= 0);
        }
        
        result = count_down.Stop();
        CPPUNIT_ASSERT(result >= 0);
        CPPUNIT_ASSERT(game_state_.test(GAME_FINISHED) == true);
        CPPUNIT_ASSERT(count_down.GetTotalMicroseconds() >= microseconds);
        CPPUNIT_ASSERT(count_down.GetRemainingMicroseconds() <= 0);

    }
private:    
    GameState game_state_;
};

CPPUNIT_TEST_SUITE_REGISTRATION(TimerTaskTest);
